package org.zhaya.sdk.swamill;


import com.google.common.collect.Lists;
import io.logz.sawmill.parser.*;
import io.logz.sawmill.utilities.JsonUtils;
import org.zhaya.sdk.processors.condition.ProcessorEnum;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class CustomExecutionStepDefinitionParser extends ExecutionStepDefinitionParser {

    public static List<ExecutionStepDefinition> parse(List<Map<String, Object>> configMapList) {
        if (configMapList == null) {
            return null;
        }
        return configMapList.stream().map(CustomExecutionStepDefinitionParser::parse).collect(Collectors.toList());
    }

    private static ExecutionStepDefinition parse(Map<String, Object> configMap) {
        String type = JsonUtils.getTheOnlyKeyFrom(configMap);

        if ("switch".equals(type)) {
            List<Map<String, Object>> executionStepConfig = JsonUtils.getList(configMap, type, true);
            return parseSwitchConditional(executionStepConfig);
        }
        Map<String, Object> executionStepConfig = JsonUtils.getMap(configMap, type, true);
        if ("if".equals(type)) {
            return parseConditional(executionStepConfig);
        }
        return parseProcessor(type, executionStepConfig);

    }

    /**
     * case 的list流经此处
     *
     * @param caseList
     * @return
     */
    private static ConditionalExecutionStepDefinition parseSwitchConditional(List<Map<String, Object>> caseList) {
        SwitchConditionalExecutionStepDefinition switchConditional =
                new SwitchConditionalExecutionStepDefinition(null, null, null);
        List<ConditionalExecutionStepDefinition> conditionalExecutionStepDefinitions = Lists.newArrayList();
        for (Map<String, Object> map : caseList) {
            Map<String, Object> condition = JsonUtils.getMap(map, ProcessorEnum.condition.name(), true);
            List<Map<String, Object>> onTrue = JsonUtils.getList(map, ProcessorEnum.then.name(), true);
            ConditionDefinition conditionDefinition = ConditionDefinitionParser.parse(condition);
            List<ExecutionStepDefinition> onTrueDefinitions = parse(onTrue);
            ConditionalExecutionStepDefinition steps =
                    new ConditionalExecutionStepDefinition(conditionDefinition, onTrueDefinitions, null);
            conditionalExecutionStepDefinitions.add(steps);
        }
        switchConditional.setCaseConditionList(conditionalExecutionStepDefinitions);
        return switchConditional;
    }

    private static ConditionalExecutionStepDefinition parseConditional(Map<String, Object> config) {
        Map<String, Object> condition = JsonUtils.getMap(config, ProcessorEnum.condition.name(), true);
        List<Map<String, Object>> onTrue = JsonUtils.getList(config, ProcessorEnum.then.name(), true);
        List<Map<String, Object>> onFalse = JsonUtils.getList(config, "else", false);

        ConditionDefinition conditionDefinition = ConditionDefinitionParser.parse(condition);
        List<ExecutionStepDefinition> onTrueDefinitions = parse(onTrue);
        List<ExecutionStepDefinition> onFalseDefinitions = parse(onFalse);
        return new ConditionalExecutionStepDefinition(conditionDefinition, onTrueDefinitions, onFalseDefinitions);
    }

    private static ProcessorExecutionStepDefinition parseProcessor(String processorType, Map<String, Object> config) {
        String name = JsonUtils.getString(config, "name", false);
        Map<String, Object> processorConfig = JsonUtils.getMap(config, "config", true);
        ProcessorDefinition processorDefinition = new ProcessorDefinition(processorType, processorConfig);

        List<Map<String, Object>> onFailure = JsonUtils.getList(config, "onFailure", false);
        List<ExecutionStepDefinition> onFailureExecutionStepDefinitions = parse(onFailure);

        List<Map<String, Object>> onSuccess = JsonUtils.getList(config, "onSuccess", false);
        List<ExecutionStepDefinition> onSuccessExecutionStepDefinitions = parse(onSuccess);

        return new ProcessorExecutionStepDefinition(processorDefinition, name, onFailureExecutionStepDefinitions, onSuccessExecutionStepDefinitions);
    }
}
